home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / source / xdme_1.84_src.lha / XDME / Lib / src / hl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-06  |  15.3 KB  |  713 lines

  1. /******************************************************************************
  2.  
  3.     MODULE
  4.     HL.c
  5.  
  6.     DESCRIPTION
  7.     ``Hierachic Lists''
  8.  
  9.     NOTES
  10.  
  11.     BUGS
  12.     none known - never tested
  13.  
  14.     TODO
  15.     connections: Connect, RemoveLock, Notify
  16.  
  17.     EXAMPLES
  18.  
  19.     SEE ALSO
  20.  
  21.     INDEX
  22.  
  23.     HISTORY
  24.     22-11-94 b_noll created
  25.  
  26. ******************************************************************************/
  27.  
  28.  
  29. /**************************************
  30.           Includes
  31. **************************************/
  32.  
  33. #include "HL.h"
  34. #include "Definitions.h"
  35. #include "xdme_base.h"
  36.  
  37. #include <stdlib.h>
  38. #include <string.h>
  39.  
  40.  
  41. #include <intuition/classes.h>
  42.  
  43. /**************************************
  44.         Global Variables
  45. **************************************/
  46.  
  47. extern int NodeNodeComparison(void *, void *);
  48. extern int NodeStringComparison(void *, const UBYTE *);
  49.  
  50. /**************************************
  51.       Internal Defines & Structures
  52. **************************************/
  53.  
  54. #define HL_OK            0
  55. #define HL_ERROR        1
  56. #define HL_NOMEM        2
  57. #define HL_NOLIST        3
  58. #define HL_DUPTREENODE        4
  59.  
  60.  
  61. struct Locker {
  62.     struct SNode  Node;
  63.     struct Locker*Base;
  64.     struct HNode *Partner;
  65.     ULONG      Attr;
  66. }; /* struct  */
  67.  
  68. #define SCAN void *
  69. #define FIND void *
  70.  
  71. /**************************************
  72.        Internal Variables
  73. **************************************/
  74.  
  75. struct HNode *HL_Root  = NULL;
  76.  
  77. /**************************************
  78.        Internal Prototypes
  79. **************************************/
  80.  
  81.  
  82. /**************************************
  83.          Macros
  84. **************************************/
  85.  
  86.  
  87. /**************************************
  88.          Implementation
  89. **************************************/
  90.  
  91. #if 0
  92. #include <proto/exec.h>
  93. static APTR allocmem (int n)
  94. {
  95.     return AllocVec (n, 0);
  96. } /* malloc */
  97.  
  98. static void freemem (APTR n)
  99. {
  100.     FreeVec (n);
  101. } /* free */
  102. #else
  103. #define allocmem malloc
  104. #define freemem free
  105. #endif
  106.  
  107.  
  108. #if 0
  109. struct LockerNode {
  110.     struct SNode   Node;
  111.     struct Locker *Base;
  112.     APTR       Partner;
  113.     ULONG       Attr;
  114. }; /* struct LockerNode */
  115.  
  116. struct Locker {
  117.     struct LockerNode Parts[2];
  118.     ULONG  Flags;
  119. }; /* struct Locker */
  120.  
  121. static __inline struct LockerNode *PartnerNode(struct LockerNode *n) {
  122.     int is_Header = (n->Base->Parts == n)? 1: 0;
  123.     return n->Base->Parts + is_Header;
  124. } /* PartnerNode */
  125.  
  126. static void PBL__DropLocks (struct LockerNode *n, struct HNode *o) {
  127.     int is_Header = (n->Base->Parts == n)? 1: 0;
  128.  
  129.     /* ---- we avoid endless loops by removing the node from our own
  130.     **        list of locks before notifying the partner, and by checking
  131.     **        if we have this node before sending ...             */
  132.  
  133.     if (SLL_Remove (&o->Locks, &n->Node)) {
  134.     DoDispatch (n->Partner, PB_CONNECT, PBA_Resolve, PartnerNode(n));
  135.  
  136.     /* ---- Only one of the 2 Partners may free the Locker */
  137.     if (is_Header)
  138.         free (n->Base);
  139.     } /* if */
  140. } /* PBL__DropLocks */
  141.  
  142. static void PBL__NotifyLocks (struct LockerNode *n, struct PB_Msg *m) {
  143.     int is_Header = (n->Base->Parts == n)? 1: 0;
  144.  
  145.     if (m->Attr == n->Attr)
  146.     if  (is_Header)        // (IsSendingPart(n))
  147.         DoSet (n->Partner, PartnerNode(n)->Attr, m->Value);
  148. } /* PBL_NotifyLocks */
  149.  
  150.  
  151. UNVOLLSTAENDIG - BRAUCHT PARTNER INITIALISIERUNG!
  152.  
  153.  
  154. /* ---- send a notification */
  155.  
  156. ULONG HL_Notify (struct GadNode *gadget, ULONG attr, APTR value, struct HNode *base) {
  157.     return GTB_Notify(gadget, attr, value, base);
  158. } /* HL_Notify */
  159.  
  160.  
  161. /* ---- remove a certain lock from base */
  162.  
  163. static void HL_RemoveLock (struct Locker *l, struct HNode *base)
  164. {
  165.     SLL_Remove (&base->Locks, &l->Node);
  166.     HL_Notify  (l->Partner, l->Attr, NULL, NULL);
  167.     DISPOSE(l);
  168. } /* HL_RemoveLock */
  169.  
  170.  
  171. /* ---- build a connection between base and its partner */
  172.  
  173. ULONG HL_Connect (struct HNode *base, struct HNode *partner, ULONG attr)
  174. {
  175.     struct Locker *l, *pl;
  176.     if (attr != N_NAME && attr != N_LIST && attr != N_VALUE)
  177.     return 0;
  178.  
  179.     if (l = malloc (sizeof (*l))) {
  180.     bzero(l, sizeof (*l));
  181.     SLL_AddHead(&base->Locks, &l->Node);
  182.     l->Partner = partner;
  183.     l->Attr   = attr;
  184.  
  185.     //if (attr == N_NAME)
  186.     //    HL_Notify(partner, attr, base->Name, base);
  187.  
  188.     //if (attr == N_VALUE)
  189.     //    HL_Notify(partner, attr, base->Value, base);
  190.  
  191.     //if (attr == N_LIST)
  192.     //    HL_Notify(partner, attr, &base->Subs, base);
  193.  
  194.     return 1;
  195.     } /* if */
  196.     return 0;
  197. } /* HL_Connect */
  198.  
  199.  
  200. AB HIER OK (HOFFE ICH)
  201.  
  202. #else
  203. void HL_RemoveLock (struct Locker *l, struct HNode *base);
  204. ULONG  HL_Notify (struct HNode *gadget, ULONG attr, APTR value, struct HNode *base);
  205. #endif
  206.  
  207.  
  208. /* ---- Find a Lock between base and its partner */
  209.  
  210. static struct Locker *HL_FindLock (struct HNode *base, APTR partner)
  211. {
  212.     struct Locker *l;
  213.     if (base)
  214.     for (l = (APTR)base->Locks.Head; l; l = (APTR)l->Node.Succ)     /* 1 */
  215.         if (l->Partner == partner)
  216.         return l;
  217.     return NULL;
  218. } /* HL_FindLock */
  219.  
  220.  
  221. /* ---- remove all connections between base and its partner */
  222.  
  223. ULONG HL_Disconnect (struct HNode *base, struct HNode *partner)
  224. {
  225.     struct Locker *l;
  226.     if (base && partner)
  227.     while ((l = HL_FindLock(base, partner)))
  228.         HL_RemoveLock(l, base);
  229.     return HL_OK;
  230. } /* HL_Disconnect */
  231.  
  232.  
  233.  
  234. /* ---- strip all locks from base */
  235.  
  236. static void HL_RemoveLocks (struct HNode *base)
  237. {
  238.     SLL_Scan(&base->Locks, (SCAN)HL_RemoveLock, base);
  239. } /* HL_RemoveLocks */
  240.  
  241.  
  242.  
  243. /* ---- notify all partners which are listening 2 attr */
  244.  
  245. static void HL_NotifyLocks (struct HNode *base, ULONG attr, APTR value)
  246. {
  247.     struct Locker *l;
  248. //printf (" StratNotificaton %d %08lx\n", attr, value);
  249.     if (base) {
  250.     base->Flags |= HLF_PRIVATESET;
  251.     for (l = (APTR)base->Locks.Head; l; l = (APTR)l->Node.Succ) {
  252. //printf (" ... %d ", l->Attr);
  253.         if (l->Attr == attr)
  254.         HL_Notify (l->Partner, attr, value, base);
  255.     }
  256.     base->Flags &= ~HLF_PRIVATESET;
  257.      }
  258. } /* HL_NotifyLocks */
  259.  
  260.  
  261.  
  262.  
  263.  
  264.  
  265.  
  266.  
  267. /* ---- get the Value instance data of a HNode */
  268.  
  269. //static
  270. struct HLAValue *HL_InstValue (struct HNode *base)
  271. {
  272.     ULONG len = sizeof (*base);
  273.  
  274.     if (!(base->Flags & HLF_VALUE))
  275.     return NULL;
  276.  
  277.     return (struct HLAValue *)(len + (ULONG)base);
  278. } /* HL_InstValue */
  279.  
  280.  
  281. /* ---- get the SubsList instance data of a HNode */
  282.  
  283. //static
  284. struct HLASubs *HL_InstSubs (struct HNode *base)
  285. {
  286.     ULONG len = sizeof (*base);
  287.  
  288.     if (!(base->Flags & HLF_SUBCARRIER) || (base->Flags & HLF_TREE))
  289.     return NULL;
  290.  
  291.     if (base->Flags & HLF_VALUE)
  292.     len += sizeof (struct HLAValue);
  293.  
  294.     return (struct HLASubs *)(len + (ULONG)base);
  295. } /* HL_InstSubs */
  296.  
  297.  
  298. /* ---- get the SubsTree instance data of a HNode */
  299.  
  300. static struct HLATree *HL_InstTree (struct HNode *base)
  301. {
  302.     ULONG len = sizeof (*base);
  303.  
  304.     if (!(base->Flags & HLF_TREE))
  305.     return NULL;
  306.  
  307.     if (base->Flags & HLF_VALUE)
  308.     len += sizeof (struct HLAValue);
  309.  
  310.     return (struct HLATree *)(len + (ULONG)base);
  311. } /* HL_InstTree */
  312.  
  313.  
  314. /* ---- change the parent slot of a HNode */
  315.  
  316. static void HL_SetParent (struct HNode *n, struct HNode *parent) {
  317.     n->Parent = parent;
  318. } /* HL_SetParent */
  319.  
  320.  
  321. /* **** Lock the SubsList of a HNode for Manipulation */
  322.  
  323. struct DList *HL_LockSubs (struct HNode *base)
  324. {
  325.     struct HLASubs  *s;
  326.  
  327.     if (!base )
  328.     return NULL;
  329.  
  330.     if (!base || !(base->Flags & HLF_SUBCARRIER) || (base->Flags & HLF_TREE))
  331.     return NULL;
  332.  
  333.     if (!base->BlockCnt++)
  334.     if (base->Locks.Head)
  335.         HL_NotifyLocks (base, HLA_Labels, (void *)~0L);
  336.  
  337.     s = HL_InstSubs(base);
  338.     //if (!base->BlockCnt++)
  339.     //      DLL_Scan (&s->Subs, (SCAN)HL_SetParent, NULL);
  340.  
  341.     return &s->Subs;
  342. } /* HL_LockSubs */
  343.  
  344.  
  345. /* **** Unlock a previously locked SubsList  */
  346.  
  347. ULONG HL_UnlockSubs (struct HNode *base)
  348. {
  349.     struct HLASubs  *s;
  350.  
  351.     if (!base || !(base->Flags & HLF_SUBCARRIER) || (base->Flags & HLF_TREE))
  352.     return HL_NOLIST;
  353.  
  354.     s = HL_InstSubs(base);
  355.  
  356.     if (!--base->BlockCnt)
  357.     DLL_Scan (&s->Subs, (SCAN)HL_SetParent, base);
  358.  
  359.     if (!base->BlockCnt)
  360.     if (base->Locks.Head)
  361.         HL_NotifyLocks (base, HLA_Labels, &s->Subs);
  362. } /* HL_UnlockSubs */
  363.  
  364.  
  365. /* ---- append a new member 2 base (notifying in Lists) */
  366.  
  367. ULONG HL_AddMember (struct HNode *base, struct HNode *member, struct HNode *where)
  368. {
  369.     struct HLATree  *t;
  370.     struct HLASubs  *s;
  371.  
  372.     if (!base || !member )
  373.     return HL_ERROR;
  374.  
  375.     if (base->Flags & HLF_TREE) {
  376.     t = HL_InstTree(base);
  377.     if (AVL_Find(&t->Subs, NodeStringComparison, member->Name))
  378.         return HL_DUPTREENODE;
  379.  
  380.     AVL_Append (&t->Subs, NodeNodeComparison, (struct TreeNode *)member);
  381.     member->Parent = base;
  382.     return HL_OK;
  383.     } /* if */
  384.  
  385.     if (!(base->Flags & HLF_SUBCARRIER))
  386.     return HL_NOLIST;
  387.  
  388.     if (!base->BlockCnt++)
  389.     if (base->Locks.Head)
  390.         HL_NotifyLocks (base, HLA_Labels, (void *)~0L);
  391.  
  392.     s = HL_InstSubs(base);
  393.     if (!where)
  394.     DLL_AddTail (&s->Subs, &member->Node);
  395.     else
  396.     DLL_AddBehind (&s->Subs, &member->Node, &where->Node);
  397.     member->Parent = base;
  398.  
  399.     if (!--base->BlockCnt)
  400.     if (base->Locks.Head)
  401.         HL_NotifyLocks (base, HLA_Labels, &s->Subs);
  402.     return HL_OK;
  403. } /* HL_AddMember */
  404.  
  405.  
  406. /* ---- remove a member from base (notifying in lists) */
  407.  
  408. ULONG HL_RemMember (struct HNode *base, struct HNode *member)
  409. {
  410.     struct HLATree  *t;
  411.     struct HLASubs  *s;
  412.  
  413.     if (!base || !member )
  414.     return HL_ERROR;
  415.  
  416.     if (base->Flags & HLF_TREE) {
  417.     t = HL_InstTree(base);
  418.     AVL_Remove (&t->Subs, NodeNodeComparison, (struct TreeNode *)member);
  419.     member->Parent = NULL;
  420.     return HL_OK;
  421.     } /* if */
  422.  
  423.     if (!(base->Flags & HLF_SUBCARRIER))
  424.     return HL_NOLIST;
  425.  
  426.     if (!base->BlockCnt++)
  427.     if (base->Locks.Head)
  428.         HL_NotifyLocks (base, HLA_Labels, (void *)~0L);
  429.  
  430.     s = HL_InstSubs(base);
  431.     DLL_Remove (&s->Subs, &member->Node);
  432.     member->Parent = NULL;
  433.  
  434.     if (!--base->BlockCnt)
  435.     if (base->Locks.Head)
  436.         HL_NotifyLocks (base, HLA_Labels, &s->Subs);
  437.     return HL_OK;
  438. } /* HL_RemMember */
  439.  
  440.  
  441. /* **** free all HL data of a node like structure */
  442.  
  443. Prototype ULONG HL_Uninit (struct HNode *n);
  444. ULONG HL_Uninit (struct HNode *n)
  445. {
  446.     struct HLATree  *t;
  447.     struct HLASubs  *s;
  448.     struct HLAValue *v;
  449.  
  450.     if (!n)
  451.     return HL_ERROR;
  452.  
  453.     if (n->Parent) {
  454.     ULONG rv;
  455.     rv = HL_RemMember (n->Parent, n);
  456.     if (rv != HL_OK)
  457.         return rv;
  458.     } /* if */
  459.  
  460.     if (n->Locks.Head)
  461.     HL_RemoveLocks (n);
  462.  
  463.     if (n->Flags & HLF_TREE) {
  464.     t = HL_InstTree(n);
  465.     AVL_ScanTree (&t->Subs, (SCAN)HL_SetParent, AVL_SCAN_INFIX);
  466.     AVL_FreeTree (&t->Subs, (SCAN)HL_Dispose);
  467.     } else if (n->Flags & HLF_SUBCARRIER) {
  468.     s = HL_InstSubs(n);
  469.     DLL_Scan (&s->Subs, (SCAN)HL_Dispose, NULL);
  470.     }
  471.  
  472.     if (n->Flags & HLF_VALUE) {
  473.     v = HL_InstValue(n);
  474.     if (v->Value)
  475.         free (v->Value);
  476.     }
  477.  
  478.     if (n->Name)
  479.     free (n->Name);
  480.  
  481.     return HL_OK;
  482. } /* HL_Uninit */
  483.  
  484.  
  485. /* **** prepare the HL part of a node like structure */
  486.  
  487. Prototype ULONG HL_Init (struct HNode *n, const UBYTE *name, struct HNode *parent, UWORD flags);
  488. ULONG HL_Init (struct HNode *n, const UBYTE *name, struct HNode *parent, UWORD flags)
  489. {
  490.     struct HLATree  *t;
  491.     struct HLASubs  *s;
  492.     struct HLAValue *v;
  493.  
  494.     n->Name        = strdup (name);
  495.     n->Locks.Head   = NULL;
  496.     n->Parent        = NULL;
  497.     n->Flags        = flags;
  498.  
  499.     if (flags & HLF_TREE) {
  500.     t = HL_InstTree(n);
  501.     AVL_Init (&t->Subs);
  502.     } else if (flags & HLF_SUBCARRIER) {
  503.     s = HL_InstSubs(n);
  504.     DLL_Init (&s->Subs);
  505.     }
  506.  
  507.     if (flags & HLF_VALUE) {
  508.     v = HL_InstValue(n);
  509.     v->Value    = strrep (NULL, "");
  510.     }
  511.  
  512.     if ( !n->Name || ((flags & HLF_VALUE) && !v->Value) ) {
  513.     HL_Uninit (n);
  514.     return HL_NOMEM;
  515.     } /* if */
  516.  
  517.     if (parent) {
  518.     ULONG rv;
  519.     if ((rv = HL_AddMember (parent, n, NULL)) != HL_OK) {
  520.         HL_Uninit (n);
  521.         return rv;
  522.     } /* if */
  523.     } /* if */
  524.  
  525.     return HL_OK;
  526. } /* HL_Init */
  527.  
  528.  
  529. /* **** dispose a HNode entry (safe) */
  530.  
  531. Prototype ULONG HL_Dispose (struct HNode *n);
  532. ULONG HL_Dispose (struct HNode *n)
  533. {
  534.     ULONG rv;
  535.     if ((rv = HL_Uninit(n)) == HL_OK)
  536.     freemem (n);
  537.     return rv;
  538. } /* HL_Dispose */
  539.  
  540.  
  541. /* **** create a new HNode entry */
  542.  
  543. struct HNode *HL_New (const UBYTE *name, struct HNode *parent, UWORD flags)
  544. {
  545.     struct HNode *n;
  546.     ULONG      rv;
  547.     ULONG      len = sizeof (struct HNode);
  548.  
  549.     if (flags & HLF_TREE)
  550.     len += sizeof (struct HLATree);
  551.     else if (flags & HLF_SUBCARRIER)
  552.     len += sizeof (struct HLASubs);
  553.  
  554.     if (flags & HLF_VALUE)
  555.     len += sizeof(struct HLAValue);
  556.  
  557.     if (n = allocmem (len)) {
  558.     bzero (n, len);
  559.     if ((rv = HL_Init(n, name, parent, flags)) != HL_OK) {
  560.         freemem (n);
  561.         return NULL;
  562.     } /* if */
  563.     } /* if */
  564.     return n;
  565. } /* HL_New */
  566.  
  567.  
  568. /* **** create a new toplevel list with systemattribute */
  569.  
  570. struct HNode * HL_SystemList (const UBYTE *name)
  571. {
  572.     if (!HL_Root)
  573.     HL_Root = HL_New("*Root*", NULL, HLF_SUBCARRIER);
  574.     if (!HL_Root)
  575.     return NULL;
  576.  
  577.     return HL_New (name, HL_Root, HLF_SUBCARRIER|HLF_SYSNODE);
  578. } /* HL_SystemList */
  579.  
  580.  
  581. /* **** lock, scan & unlock a list */
  582.  
  583. void HL_Scan (struct HNode *n, void (*scan)(struct HNode*, void*, int), void *userdata)
  584. {
  585.     struct DList *l;
  586.     if ((l = HL_LockSubs (n))) {
  587.     DLL_Scan     (l, (SCAN)scan, userdata);
  588.     HL_UnlockSubs(n);
  589.     //} else if ((t = HL_InstTree (n)))
  590.     //      AVL_ScanTree (&t->Subs, (SCAN)scan, AVL_SCAN_POSTFIX, userdata);
  591.     } /* if */
  592. } /* HL_Scan */
  593.  
  594. struct HNode *HL_Find (struct HNode *n, int (*find)(struct HNode*, void*, int), void *userdata)
  595. {
  596.     struct HLASubs *s;
  597.     struct HLATree *t;
  598.  
  599.     if ((s = HL_InstSubs (n)))
  600.     return (struct HNode *)DLL_Find (&s->Subs, (FIND)find, userdata);
  601.     else if ((t = HL_InstTree (n)))
  602.     return (struct HNode *)AVL_Find (&t->Subs, (FIND)find, userdata);
  603.     else
  604.     return NULL;
  605. } /* HL_Find */
  606.  
  607.  
  608.  
  609.  
  610. #ifndef freemem
  611. void _STD_10000_HL_Exitus (void) {
  612.     HL_Dispose(HL_Root);
  613. } /* HL_Exitus */
  614. #endif
  615.  
  616. /******************************************************************************
  617. *****  END HL.c
  618. ******************************************************************************/
  619.  
  620. #if 0
  621.  
  622. static ULONG HL__ClassSize (struct HClass *c) {
  623.     ULONG s = 0;
  624.     while (c) {
  625.     s += c->Size;
  626.     c = c->Superclass;
  627.     } /* while */
  628.     return s;
  629. } /* HL__ClassSize */
  630.  
  631. static ULONG HL__Dispatcher (struct HNode *n, struct HClass *class, ULONG *msg)
  632. {
  633.     switch (*msg) {
  634.     case OM_DISPOSE:
  635.     HL_Uninit(n);
  636.     free (n);
  637.     break;
  638.     case OM_NEW:
  639.     if ((n = malloc(HL__ClassSize((struct HClass *)n)))) {
  640.         if (HL_Init(n, (UBYTE *)*(msg+1), (struct HNode *)*(msg+2), *(msg+3)) == HL_OK)
  641.         return (ULONG)n;
  642.         free (n);
  643.     } /* if */
  644.     return NULL;
  645.     } /* switch */
  646.     return 0;
  647. } /* HL__Dispatcher */
  648.  
  649.  
  650. ULONG HL__Coerce (struct HNode *n, struct HClass *c, ULONG *msg)
  651. {
  652.     return c->Dispatcher(n, c, msg);
  653. } /* HL__Coerce */
  654.  
  655. ULONG HL__Method (struct HNode *n, ULONG *msg)
  656. {
  657.     return HL__Coerce(n, n->Class, msg);
  658. } /* HL_Method */
  659.  
  660. struct HClass HRoot = {
  661.     HL__Dispatcher,
  662.     sizeof (struct HNode) + sizeof (struct HLAValue) + sizeof (struct HLASubs),
  663.     NULL
  664. };
  665.  
  666. struct HClass HLSubCarrier = {
  667.     HL__Dispatcher,
  668.     sizeof (struct HLASubs),
  669.     &HRoot
  670. };
  671.  
  672. struct HClass HLValCarrier = {
  673.     HL__Dispatcher,
  674.     sizeof (struct HLAValue),
  675.     &HLSubCarrier
  676. };
  677.  
  678. struct HNode *HL__New (struct HClass *c, UBYTE *name, struct HNode *parent, WORD flags) {
  679.     ULONG new[] = { OM_NEW, 0,0,0,0 };
  680.     new[1] = (ULONG)name;
  681.     new[2] = (ULONG)parent;
  682.     new[3] = flags;
  683.     return (struct HNode *)HL__Coerce ((struct HNode *)c, c, new);
  684. }
  685.  
  686. ULONG HL__SetN (struct HNode *n, ...)
  687. {
  688.     ULONG set[] = { OM_SET, NULL };
  689.     set[1] = (ULONG)((&n)+1);
  690.     return HL__Method(n, set);
  691. } /* HL__SetN */
  692.  
  693. ULONG  HL__SetS (struct HNode *n, ULONG attr, ULONG value)
  694. {
  695.     return HL__SetN (n, attr, value, TAG_DONE);
  696. } /* HL__SetS */
  697.  
  698. void HL__GetS (struct HNode *n, ULONG attr, ULONG *value)
  699. {
  700.     ULONG get[] = { OM_GET, 0, 0 };
  701.     get[1] = attr;
  702.     get[2] = (ULONG)value;
  703.     HL__Method(n, get);
  704. } /* HL__GetS */
  705.  
  706. void HL__Dispose (struct HNode *n)
  707. {
  708.     ULONG dispose = OM_DISPOSE;
  709.     HL__Method (n, &dispose);
  710. } /* HL_Dispose */
  711.  
  712. #endif
  713.